package com.ming.common.dynamic.loader.jar_loader;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

/**
 * 将外部jar读入内存中
 */
public class DynamicJar {
    String[] filePath;
    String fullClassName;

    private URLClassLoader urlClassLoader;

    public DynamicJar(String... filePath) {
        this.filePath = filePath;
    }

    public static DynamicJar init(String... filePath) {
        System.out.println("初始化jar filePath:" + filePath);
        return new DynamicJar(filePath);
    }

    public DynamicJar fullClassName(String fullClassName) {
        this.fullClassName = fullClassName;
        return this;
    }

    public Class<?> load(String fullClassName) {
        try {
            URL url = new File(filePath[0]).toURI().toURL();
            urlClassLoader = new URLClassLoader(new URL[]{url});
            Class<?> aClass = urlClassLoader.loadClass(fullClassName);
            return aClass;
        } catch (MalformedURLException | ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

/*    public void load(DynamicClass dynamicClass) {
        try {
            //URL url = new File(filePath[0]).toURI().toURL();
            //urlClassLoader = new URLClassLoader(new URL[]{url});

            byte[] classBytes = dynamicClass.getClassData();
            ClassReader classReader = new ClassReader(classBytes);
            ImportInfoCollector importInfoCollector = new ImportInfoCollector();
            classReader.accept(importInfoCollector, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
            List<ImportInfo> importList = importInfoCollector.getList();
            for (ImportInfo importInfo : importList){
                System.out.println();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void loadAll() {
        try {
            for (String path : filePath){
                File jarFile = new File(path);
                URL url = new File(path).toURI().toURL();
                urlClassLoader = new URLClassLoader(new URL[]{url});
                JarFile jar = new JarFile(jarFile);
                Enumeration<JarEntry> entries = jar.entries();
                while (entries.hasMoreElements()) {
                    JarEntry entry = entries.nextElement();
                    if (entry.getName().endsWith(".class")) {
                        String className = entry.getName().replace("/", ".").replace(".class", "");
                        // 先检查类是否存在
                        System.out.println(className);
                        if (classExists(urlClassLoader, className)) {
                            urlClassLoader.loadClass(className);
                        }
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }



    public byte[] loadClassFromURLClassLoader(ClassLoader classLoader, String className) {
        try {
            Class<?> loadedClass = classLoader.loadClass(className);

            InputStream classStream = loadedClass.getResourceAsStream("/" + className.replace('.', '/') + ".class");
            return readStreamToBytes(classStream);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }



    private static boolean classExists(ClassLoader classLoader, String className) {
        try {
            Class.forName(className, false, classLoader);
            return true;
        }catch (ClassNotFoundException e) {
            return false;
        }catch (Exception e) {
            return false;
        }
    }*/

    public byte[] loadClassFromURLClassLoader(String className) {
        try {
            Class<?> loadedClass = urlClassLoader.loadClass(className);
            InputStream classStream = loadedClass.getResourceAsStream("/" + className.replace('.', '/') + ".class");
            return readStreamToBytes(classStream);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    public byte[] loadClassFromURLClassLoader(URLClassLoader urlClassLoader, String className) {
        try {
            Class<?> loadedClass = urlClassLoader.loadClass(className);
            InputStream classStream = loadedClass.getResourceAsStream("/" + className.replace('.', '/') + ".class");
            return readStreamToBytes(classStream);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    private byte[] readStreamToBytes(InputStream in) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = in.read(buffer)) != -1) {
            out.write(buffer, 0, bytesRead);
        }
        return out.toByteArray();
    }

    public URLClassLoader getUrlClassLoader() {
        return urlClassLoader;
    }
}

